//
//  NetworkPlugin.swift
//  Moya插件
//  主要用来处理一些接口数据签名和加密
//
//  Created by smile on 2019/4/27.
//  Copyright © 2019 ixuea. All rights reserved.
//

import Foundation

// 导入网络框架
import Moya

//当前版本一定要导入
//不然有些方法不会回调
import Result

/// Notify a request's network activity changes (request begins or ends).
public final class NetworkPlugin: PluginType {
    
    /// 在完成（completion）前调用
    /// 所以可以在这里校验响应签名是否正确
    /// 当然也可以完成接口响应的解密
    ///
    /// - Parameters:
    ///   - result: <#result description#>
    ///   - target: <#target description#>
    /// - Returns: <#return value description#>
    public func process(_ result: Result<Moya.Response, MoyaError>, target: TargetType) -> Result<Moya.Response, MoyaError>{
        print("NetworkPlugin process:\(result)")
        
        switch result {
        case let .success(response):
            //请求成功
            let urlResponse = response.response as! HTTPURLResponse

            let data = response.data
            
            if let sign = urlResponse.allHeaderFields["Sign"] as? String{
                //有签名
                //所以要校验数据
                
                //真实项目中
                //如果所有接口响应有签名
                //如果判断没有签名
                //就直接抛出错误
                print("NetworkPlugin process:\(target)")

                //将返回的数据转为字符串
                let dataString = String(data: data, encoding: String.Encoding.utf8)
                
                //获取字符串签名
                let localSign=DigestUtil.sha1(dataString!)
                
                if localSign == sign {
                    //签名正确
                    //什么也不做
                    print("NetworkPlugin process sign correct:\(target)")
                }else{
                    //签名不正确
                    print("NetworkPlugin process sign incorrect:\(target)")
                    
                    //抛出异常
                    //让后续的代码处理
                    //由于不能自定义错误
                    //就返回一个字符串映gac射错误就行了
                    return Result.failure(MoyaError.stringMapping(response))
                }
            }else{
                print("NetworkPlugin process not sign:\(target)")
            }
            
            
            //响应解密
            if target.path.hasSuffix("v3/orders.json") && target.method == Moya.Method.get {
                //该接口需要解密
                //真实项目中可能所有接口都会加密
                //所以就不用判断了
                
                //我们这里为了降低课程难度
                //所以只加密这个几个接口
                
                //数据解密
                
                //将返回的数据转为字符串
                let dataString = String(data: data, encoding: String.Encoding.utf8)
                
                if let decryptString=DigestUtil.decryptAES(dataString!) {
                    //解密成功
                    //就认为数据没问题
                    //这里就不再判断内容是否正确了
                    
                    //将解密后的字符串转为data
                    let data=decryptString.data(using: .utf8)!
                    
                    //更改header
                    //因为对于加密的数据
                    //服务端返回的Content-Type为text/plain
                    //有些框架会自动处理所以需要更改
                    //这里其实可以不用更改
                    //因为Moya框架不会自动处理
                    var newHeaders = urlResponse.allHeaderFields as! [String:String]
                    newHeaders["Content-Type"]="application/json"
                    
                    //创建一个新的HTTPURLResponse
                    //因为要更改Header
                    
                    //原来的headers是只读的
                    let newUrlResponse=HTTPURLResponse(url: urlResponse.url!, statusCode: urlResponse.statusCode, httpVersion: "HTTP/1.1", headerFields: newHeaders)
                    
                    //创建一个新的Moya.Response
                    //因为要更改data
                    
                    //原来的response是只读的
                    let newResponse=Moya.Response(statusCode: response.statusCode, data: data, request: response.request, response: newUrlResponse)
                    
                    print("NetworkPlugin process decrypt success:\(target)")
                    
                    //返回新创建的Result
                    return Result.success(newResponse)
                }else{
                    print("NetworkPlugin process decrypt error:\(target)")
                    
                    //抛出异常
                    return Result.failure(MoyaError.stringMapping(response))
                }
            }
            
        case .failure(_):
            //失败
            //这里不处理
            //让后续的代码处理
            
            break
        }
        
        return result
    }
   
}




